﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OCR.Digital.Comm
{
    /// <summary>
    /// 图片处理类
    /// </summary>
    public class BitmapHandle
    {
        private Bitmap _bitmap;

        public BitmapHandle(Bitmap bitmap)
        {
            this._bitmap = new Bitmap(bitmap); //转换为Format32bppRgb
        }

        public Bitmap GetBitmap()
        {
            return this._bitmap;
        }

        /// <summary>
        /// 灰度转换,根据RGB计算并逐点替换
        /// </summary>
        public Bitmap GrayByPixels()
        {
            for (var i = 0; i < _bitmap.Height; i++)
            {
                for (var j = 0; j < _bitmap.Width; j++)
                {
                    var pxColor = _bitmap.GetPixel(j, i);
                    var toGray = Convert.ToInt32(pxColor.R * 0.299 + pxColor.G * 0.587 + 0.114 * pxColor.B);
                    _bitmap.SetPixel(j, i, Color.FromArgb(toGray, toGray, toGray));
                }
            }
            return _bitmap;
        }
        /// <summary>
        /// 图片二值化,使图片变成2中颜色（黑/白色）
        /// 取图片平均灰度作为阀值，低于该阀值全部为0，高于阀值全部为255
        /// </summary>
        public Bitmap ConvertPixels()
        {
            List<int> lsColor = new List<int>();
            //int avg = 0;
            //int num = 0;
            for (int i = 0; i < _bitmap.Width; i++)
            {
                for (int j = 0; j < _bitmap.Height; j++)
                {
                    lsColor.Add(_bitmap.GetPixel(i, j).R);
                }
            }
            double average = lsColor.Average();
            for (int i = 0; i < _bitmap.Width; i++)
            {
                for (int j = 0; j < _bitmap.Height; j++)
                {
                    //获取该点的像素的RGB的颜色
                    Color color = _bitmap.GetPixel(i, j);
                    if ((color.R + color.G + color.B) / 3 > average)
                    {
                        _bitmap.SetPixel(i, j, Color.White);
                    }
                    else
                    {
                        _bitmap.SetPixel(i, j, Color.Black);
                    }
                }
            }
            return _bitmap;
        }
        /// <summary>
        /// 去掉噪点
        /// </summary>
        /// <param name="dgGrayValue"></param>
        /// <param name="maxNearPoints"></param>
        public Bitmap ClearNoise(int dgGrayValue, int maxNearPoints)
        {
            //int xSpan, ySpan, tmpX, tmpY;
            //逐点判断
            for (var i = 0; i < _bitmap.Width; i++)
                for (var j = 0; j < _bitmap.Height; j++)
                {
                    var piexl = _bitmap.GetPixel(i, j);
                    if (piexl.R < dgGrayValue)
                    {
                        var nearDots = 0;
                        //判断周围8个点是否全为空
                        if (i == 0 || i == _bitmap.Width - 1 || j == 0 || j == _bitmap.Height - 1)  //边框全去掉
                        {
                            _bitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));
                        }
                        else
                        {
                            if (_bitmap.GetPixel(i - 1, j - 1).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i, j - 1).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i + 1, j - 1).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i - 1, j).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i + 1, j).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i - 1, j + 1).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i, j + 1).R < dgGrayValue) nearDots++;
                            if (_bitmap.GetPixel(i + 1, j + 1).R < dgGrayValue) nearDots++;
                        }

                        if (nearDots < maxNearPoints)
                            _bitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));   //去掉单点 && 粗细小3邻边点
                    }
                    else  //背景
                        _bitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));
                }
            return _bitmap;

        }
        /// <summary>
        /// 扭曲图片校正
        /// </summary>
        public Bitmap ReSetBitMap()
        {
            Graphics g = Graphics.FromImage(_bitmap);
            Matrix X = new Matrix();
            //  X.Rotate(30);
            X.Shear((float)0.16666666667, 0);   //  2/12
            g.Transform = X;
            // Draw image
            //Rectangle cloneRect = GetPicValidByValue(128);  //Get Valid Pic Rectangle
            Rectangle cloneRect = new Rectangle(0, 0, _bitmap.Width, _bitmap.Height);
            Bitmap tmpBmp = _bitmap.Clone(cloneRect, _bitmap.PixelFormat);
            g.DrawImage(tmpBmp,
                new Rectangle(0, 0, _bitmap.Width, _bitmap.Height),
                 0, 0, tmpBmp.Width,
                 tmpBmp.Height,
                 GraphicsUnit.Pixel);

            return tmpBmp;
        }
        /// <summary>
        /// 裁剪图片多余空白边缘(上下左右)
        /// </summary>
        /// <param name="bm"></param>
        /// <returns></returns>
        public Bitmap CutBitMap()
        {
            List<int> listX = new List<int>();
            List<int> listY = new List<int>();
            for (int i = 0; i < _bitmap.Width; i++)
            {
                int cntWhite = 0;
                for (int j = 0; j < _bitmap.Height; j++)
                {
                    Color c = _bitmap.GetPixel(i, j);
                    if (IsWhite(c)) cntWhite++;
                }
                //找到列像素不是白色的加到数组里去，最后跟进min/max拿出最小、最大边界值
                if (cntWhite != _bitmap.Height) listX.Add(i);
            }
            for (int i = 0; i < _bitmap.Height; i++)
            {
                int cntWhite = 0;
                for (int j = 0; j < _bitmap.Width; j++)
                {
                    Color c = _bitmap.GetPixel(j, i);
                    if (IsWhite(c)) cntWhite++;
                }
                //找到行像素不是白色的加到数组里去，最后跟进min/max拿出最小、最大边界值
                if (cntWhite != _bitmap.Width) listY.Add(i);
            }
            Bitmap bitMap = new Bitmap((listX.Max() - listX.Min() + 1), (listY.Max() - listY.Min() + 1));
            using (Graphics g = Graphics.FromImage(bitMap))
            {
                //注意图片的xy轴是按照第四象限取的
                g.DrawImage(_bitmap,
                    new Rectangle(0, 0, bitMap.Width, bitMap.Height),
                    new Rectangle(listX.Min(), listY.Min(), bitMap.Width, bitMap.Height),
                    GraphicsUnit.Pixel);
            }
            _bitmap = bitMap;
            return bitMap;
        }
        /// <summary>
        /// 切割图片(按纵向空白区分切割）
        /// 
        /// </summary>
        /// <returns></returns>
        public List<Bitmap> SplitBitMap()
        {
            List<Bitmap> bs = new List<Bitmap>();
            int si = -1; //start index
            int ei = 0;  //end index
            for (int i = 0; i < _bitmap.Width; i++)
            {
                int cntWhite = 0;
                for (int j = 0; j < _bitmap.Height; j++)
                {
                    Color c = _bitmap.GetPixel(i, j);
                    if (IsWhite(c)) cntWhite++;
                }
                bool isWhite = cntWhite == _bitmap.Height;//是否是白色
                //如果当前列是白色，且有开始的索引，说明又找到了一张图片
                //(是白色，且找到开始索引) 或(不是白色，但已经是最后一行)
                if ((isWhite && si >= 0) || (!isWhite && i == _bitmap.Width - 1))
                {
                    ei = i; //找到结束的索引
                    //抓取图片，备注：最后一张图片像素要+1
                    Bitmap bm = new Bitmap((i + 1 == _bitmap.Width) ? ei - si + 1 : ei - si, _bitmap.Height);
                    using (Graphics g = Graphics.FromImage(bm))
                    {
                        //注意图片的xy轴是按照第四象限取的
                        g.DrawImage(_bitmap, new Rectangle(0, 0, bm.Width, bm.Height), new Rectangle(si, 0, bm.Width, bm.Height), GraphicsUnit.Pixel);
                    }
                    bs.Add(bm);
                    //初始化
                    si = -1;
                }
                else if (!isWhite)
                {
                    if (si < 0) si = i; //找到开始的索引
                }
            }
            return bs;
        }
        /// <summary>
        /// 判断颜色是否为白色
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private bool IsWhite(Color c)
        {
            //if (c == Color.White)
            if (c.R == 255 && c.G == 255 && c.B == 255)
                return true;
            else return false;
        }
        /// <summary>
        /// 裁剪图片
        /// </summary>
        /// <param name="b"></param>
        /// <param name="startX"></param>
        /// <param name="startY"></param>
        /// <param name="iWidth"></param>
        /// <param name="iHeight"></param>
        /// <returns></returns>
        public Bitmap Cut(Bitmap b, int startX, int startY, int iWidth, int iHeight)
        {
            if (b == null) return null;
            int w = b.Width;
            int h = b.Height;
            if (startX >= w || startY >= h) return null;

            if (startX + iWidth > w)
            {
                iWidth = w - startX;
            }
            if (startY + iHeight > h)
            {
                iHeight = h - startY;
            }
            try
            {
                Bitmap bmpOut = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb);
                Graphics g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(startX, startY, iWidth, iHeight), GraphicsUnit.Pixel);
                g.Dispose();
                return bmpOut;
            }
            catch
            {
                return null;
            }
        }
    }
}
